﻿// Decompiled with JetBrains decompiler
// Type: Microsoft.InfoCards.X509LogoTypeExtension
// Assembly: infocard, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
// MVID: 8E14765A-6610-409A-BA36-099A0642905D
// Assembly location: E:\git\ALLIDA\windll\infocard.exe

using Microsoft.InfoCards.Diagnostics;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;

namespace Microsoft.InfoCards
{
  internal sealed class X509LogoTypeExtension : X509Extension
  {
    private List<X509Logo> m_logos = new List<X509Logo>();
    private const string szOID_LOGO_TYPES = "1.3.6.1.5.5.7.1.12";
    private const byte OctetStringTag = 4;
    private const byte ObjectIdentifierTag = 6;
    private const byte StringTag = 22;
    private const byte SequenceTag = 48;
    private const byte DirectTag = 160;
    private const byte IndirectTag = 161;
    private const byte AudioLogoTypeDataTag = 161;
    private bool m_decodePathComplete;

    public List<X509Logo> Logos
    {
      get
      {
        return this.m_logos;
      }
    }

    public void TryDecodeExtension()
    {
      try
      {
        this.DecodeExtension();
      }
      catch (Exception ex)
      {
        if (InfoCardTrace.IsFatal(ex))
          InfoCardService.Crash(ex);
        InfoCardTrace.TraceAndLogException(ex);
      }
      this.m_decodePathComplete = true;
    }

    public X509LogoTypeExtension(byte[] rawData)
      : base("1.3.6.1.5.5.7.1.12", rawData, false)
    {
    }

    public static X509LogoTypeExtension FromCertificate(
      X509Certificate2 certificate)
    {
      if (certificate.Extensions == null || certificate.Extensions["1.3.6.1.5.5.7.1.12"] == null)
        return (X509LogoTypeExtension) null;
      return new X509LogoTypeExtension(certificate.Extensions["1.3.6.1.5.5.7.1.12"].RawData);
    }

    public override void CopyFrom(AsnEncodedData asnEncodedData)
    {
      base.CopyFrom(asnEncodedData);
      this.Critical = false;
      this.m_decodePathComplete = false;
    }

    public override string ToString()
    {
      return base.ToString();
    }

    private void DecodeExtension()
    {
      BinaryReader br = (BinaryReader) new InfoCardBinaryReader((Stream) new MemoryStream(this.RawData));
      ASCIIEncoding asciiEncoding = new ASCIIEncoding();
      this.VerifyByte(br.ReadByte(), (byte) 48);
      this.ReadAsnByteLength(br);
      while (!this.ReachedEndPosition(br.BaseStream.Position, br.BaseStream.Length))
      {
        Dictionary<Oid, byte[]> hashes = new Dictionary<Oid, byte[]>();
        List<string> fileLocations = new List<string>();
        X509LogoType logoType = (X509LogoType) br.ReadByte();
        long position = br.BaseStream.Position;
        long num1 = (long) this.ReadAsnByteLength(br);
        long num2 = br.BaseStream.Position + num1;
        if (X509LogoType.Subject != logoType && X509LogoType.Issuer != logoType)
          throw InfoCardTrace.ThrowHelperError((Exception) new LogoValidationException(SR.GetString("LogoUnsupportedType")));
        byte input1 = br.ReadByte();
        this.VerifyByte(input1, new byte[2]
        {
          (byte) 160,
          (byte) 161
        });
        this.ReadAsnByteLength(br);
        if ((byte) 161 == input1)
          throw InfoCardTrace.ThrowHelperError((Exception) new LogoValidationException(SR.GetString("LogoUnsupportedIndirectReferences")));
        this.VerifyByte(br.ReadByte(), (byte) 48);
        this.ReadAsnByteLength(br);
        byte input2 = br.ReadByte();
        bool flag;
        if ((byte) 161 == input2)
        {
          flag = false;
          InfoCardTrace.TraceAndLogException((Exception) new LogoValidationException(SR.GetString("LogoUnsupportedAudio")));
          this.VerifyByte(br.ReadByte(), (byte) 48);
        }
        else
        {
          flag = true;
          this.VerifyByte(input2, (byte) 48);
        }
        this.ReadAsnByteLength(br);
        this.VerifyByte(br.ReadByte(), (byte) 48);
        this.ReadAsnByteLength(br);
        this.VerifyByte(br.ReadByte(), (byte) 22);
        int count1 = this.ReadAsnByteLength(br);
        string mediaType = asciiEncoding.GetString(br.ReadBytes(count1));
        this.VerifyByte(br.ReadByte(), (byte) 48);
        int num3 = this.ReadAsnByteLength(br);
        long endPosition1 = br.BaseStream.Position + (long) num3;
        while (!this.ReachedEndPosition(br.BaseStream.Position, endPosition1))
        {
          this.VerifyByte(br.ReadByte(), (byte) 48);
          this.ReadAsnByteLength(br);
          this.VerifyByte(br.ReadByte(), (byte) 48);
          int num4 = this.ReadAsnByteLength(br);
          long num5 = br.BaseStream.Position + (long) num4;
          Oid index = this.ReadObjectIdentifier(br);
          br.BaseStream.Position = num5;
          this.VerifyByte(br.ReadByte(), (byte) 4);
          int count2 = this.ReadAsnByteLength(br);
          byte[] numArray = br.ReadBytes(count2);
          hashes[index] = numArray;
        }
        this.VerifyByte(br.ReadByte(), (byte) 48);
        int num6 = this.ReadAsnByteLength(br);
        long endPosition2 = br.BaseStream.Position + (long) num6;
        while (!this.ReachedEndPosition(br.BaseStream.Position, endPosition2))
        {
          this.VerifyByte(br.ReadByte(), (byte) 22);
          int count2 = this.ReadAsnByteLength(br);
          fileLocations.Add(asciiEncoding.GetString(br.ReadBytes(count2)));
        }
        if (br.BaseStream.Position != num2)
          br.BaseStream.Position = num2;
        if (flag)
          this.m_logos.Add((X509Logo) new X509ImageLogo(logoType, mediaType, hashes, fileLocations));
      }
    }

    private void VerifyByte(byte input, byte[] expected)
    {
      foreach (int num in expected)
      {
        if (num == (int) input)
          return;
      }
      throw InfoCardTrace.ThrowHelperError((Exception) new LogoValidationException(SR.GetString("LogoInvalidLogoType")));
    }

    private void VerifyByte(byte input, byte expected)
    {
      if ((int) input != (int) expected)
        throw InfoCardTrace.ThrowHelperError((Exception) new LogoValidationException(SR.GetString("LogoInvalidLogoType")));
    }

    private bool ReachedEndPosition(long currentPosition, long endPosition)
    {
      if (currentPosition > endPosition)
        throw InfoCardTrace.ThrowHelperError((Exception) new LogoValidationException(SR.GetString("LogoInvalidCertificateLength")));
      return currentPosition == endPosition;
    }

    private int ReadAsnByteLength(BinaryReader br)
    {
      byte num1 = br.ReadByte();
      if (((int) num1 & 128) == 0)
        return (int) num1;
      int num2 = (int) num1 & (int) sbyte.MaxValue;
      if (num2 < 1 || num2 > 4)
        throw InfoCardTrace.ThrowHelperError((Exception) new LogoValidationException(SR.GetString("LogoInvalidAsnLength")));
      byte[] numArray = br.ReadBytes((int) num1 & (int) sbyte.MaxValue);
      int num3 = 0;
      foreach (int num4 in numArray)
        num3 = num4 + (num3 << 8);
      return num3;
    }

    private Oid ReadObjectIdentifier(BinaryReader br)
    {
      this.VerifyByte(br.ReadByte(), (byte) 6);
      int count = this.ReadAsnByteLength(br);
      byte[] numArray = br.ReadBytes(count);
      StringBuilder stringBuilder = new StringBuilder();
      stringBuilder.AppendFormat("{0}.{1}.", (object) ((int) numArray[0] / 40), (object) ((int) numArray[0] % 40));
      for (int index = 1; index < count; ++index)
      {
        stringBuilder.Append(numArray[index].ToString((IFormatProvider) CultureInfo.InvariantCulture));
        if (index != count - 1)
          stringBuilder.Append('.');
      }
      return new Oid(stringBuilder.ToString());
    }
  }
}
